
/* C++标准库区 */
#include<stdio.h>
#include<iostream>
#include<string>


/* 系统头文件引用区 */
#include"init.h"

using namespace std;

/* 全局控制变量 */

//系统命令分类器
CMD::OrderChecker sys_OrderChecker;

//全局grant/revoke权限解析器
Rights::RightChecker sys_RightChecker;

int relogin = 0;


/* 主函数 */

signed main(){
    //系统提示信息
    showSysInfo();
    //help用法说明
    showSysHelp();
    //索引信息读取
    DBIndex::IndexKeeperReader(sys_IndexKeeper);

    //重新登陆标记
    relogin_flag:relogin = 0;

    //登录验证
    while(1){
        printf("username:");
        getline(cin,cur_user);
        if(cur_user == "exit"){
            /*程序收尾阶段*/
            sys_UserChecker.WriteFile();
            sys_ViewKeeper.__writeData();
            DBIndex::IndexKeeperWriter(sys_IndexKeeper);
            return 0;
        }
        printf("password:");
        string paswd = "";
        getline(cin,paswd);
        DBUser::UserInfo one;
        int user_ret = sys_UserChecker.getUser(cur_user,one);
        if(user_ret < 0 || one.password != paswd){
            printf("login wrong,please confirm your account\n");
            continue;
        }
        if(one.password == paswd){
            printf("Welcome to SavenDB!\n");
            break;
        }
    }

    cout << "[set user]:" << cur_user << endl;

    //通知grant/revoke权限解析器当前的用户名称
    sys_RightChecker.setUser(cur_user);
    
    string line = "";
    while(1){
        string cli_flag = cur_user + "@SavenDB >"; 
        cout << cli_flag;
        //接收语句并分类
        line = CMD::dbget(';',cli_flag);
        //
        if(line == "relogin;"){
            relogin = 1;
            break;
        }else if(line == "help database;"){
            help_database();
            continue;
        }else if(line.find("help table") != line.npos){
            //获取一个表格信息
            std::string one = SavenUtils::trim(SavenUtils::Split_first(line,";"));
            std::stringstream ss(one);
            std::string tbname;
            ss >> tbname >> tbname >> tbname;
            help_OneDataBase(tbname);
            continue;
        }else if(line.find("help view") != line.npos){
            //获取一个视图信息
            std::string one = SavenUtils::trim(SavenUtils::Split_first(line,";"));
            std::stringstream ss(one);
            std::string tbname;
            ss >> tbname >> tbname >> tbname;
            help_OneView(tbname);
            continue;
        }else if(line.find("help index") != line.npos){
            //获取索引的信息
            std::string one = SavenUtils::trim(SavenUtils::Split_first(line,";"));
            std::stringstream ss(one);
            std::string indexname;
            ss >> indexname >> indexname >> indexname;
            help_OneIndex(indexname);
            continue;
        }
        //
        CMD::orderType ty = sys_OrderChecker.check(line);
        printf("ty == %d\n",(int)ty);
        if(ty == CMD::orderType::SYS_QUIT){
            break;
        }else if(ty == CMD::orderType::SYS_CLEAR){
            system("clear");
            continue;
        }else if(ty == CMD::orderType::SYS_HELP){
            showSysInfo();
            continue;
        }else if(ty == CMD::orderType::RUN_SQL){
            ty = sys_OrderChecker.sql_check(line);
            printf("sql_check:ty == %d\n",(int)ty);
            if(ty == CMD::SQL_GRANT){
                printf("[CMD::SQL_GRANT]\n");
                sys_RightChecker.parse_grant(line,sys_UserChecker);
            }else if(ty == CMD::SQL_REVOKE){
                printf("[CMD::SQL_REVOKE]\n");
                sys_RightChecker.parse_revoke(line,sys_UserChecker);
            }else{
                // printf("input-else\n");
                // sql运行器-先分类后运行
                /* //表操作语句
                 * create table
                 * create view
                 * create index
                 * drop table
                 * drop view
                 * drop index
                 * alter table
                 * //元组操作语句
                 * select
                 * update
                 * delete
                 * insert
                */
                //
                int ret = 0;
                int outer = 0;
                //元组操作语句权限判断
                if(ty == CMD::orderType::SQL_SELECT){
                    ret = pick_select(line,sys_UserChecker);
                    outer = 1;
                }else if(ty == CMD::orderType::SQL_UPDATE){
                    ret = pick_update(line,sys_UserChecker);
                }else if(ty == CMD::orderType::SQL_DELETE){
                    ret = pick_delete(line,sys_UserChecker);
                }else if(ty == CMD::orderType::SQL_INSERT){
                    ret = pick_insert(line,sys_UserChecker);
                }
                //创建/删除/修改表的权限判断
                //只有在运行成功后才能够允许注册信息
                std::string objname = "";
                std::string objtype = "";
                if(ty == CMD::orderType::SQL_CREATE){
                    ret = pick_create(line,sys_UserChecker,objname,objtype);
                }else if(ty == CMD::orderType::SQL_DROP){
                    ret = pick_drop(line,sys_UserChecker,objname,objtype);
                }
                //把类型名设置为小写
                objtype = SavenUtils::StringtoLower(objtype);
                //索引判定
                std::string index_tbname = "";//索引所在的表名称
                if(objtype == "index"){
                    //根据操作类型获取索引名称
                    int index_ret = 0;
                    if(ty == CMD::orderType::SQL_CREATE){
                        index_ret = getTableName_CreateIndex(line,index_tbname);
                    }else if(ty == CMD::orderType::SQL_DROP){
                        //获取要删除的索引的名称
                        index_ret = getTableName_DropIndex(line,index_tbname);
                    }
                    //根据结果启动索引的创建与删除操作
                    if(index_ret < 0){
                        printf("[error]-no on-table to create/drop index\n");
                        ret = -1;//不允许运行
                    }else{
                        printf("index_tablename = %s\n",index_tbname.c_str());
                        std::string opty = "";
                        if(ty == CMD::orderType::SQL_CREATE){
                            opty = "create";
                        }else if(ty == CMD::orderType::SQL_DROP){
                            opty = "drop";
                        }
                        printf("opty = %s\n",opty.c_str());
                        if(sys_UserChecker.admit(cur_user,index_tbname,opty)){
                            //该用户拥有在该表上的create/drop权限
                        }else{
                            //没有权限-不允许运行
                            printf("[error]-no right on table [%s] to create index\n",index_tbname.c_str());
                            ret = -1;
                        }
                    }
                    //如果找到索引对应的表 且 允许添加/删除 则 尝试添加/删除
                    if(ret != -1 && ty == CMD::orderType::SQL_CREATE){
                        int index_rett = sys_IndexKeeper.addIndex(index_tbname,objname,line);
                        if(index_rett < 0){
                            ret  = -1;//协调器不允许添加
                        }
                    }else if(ret != -1 && ty == CMD::orderType::SQL_DROP){
                        int index_rett = sys_IndexKeeper.delIndex(objname);
                        if(index_rett < 0){
                            ret  = -1;//协调器不允许删除
                        }
                    }
                }
                //检查权限
                if(ret < 0){
                    printf("[error]-pick_sys not allow to run\n");
                    continue;
                }
                printf("[ok]-allow to run\n");
                //
                ret = sysRun(line,outer);
                printf("sysRun ret = %d\n",ret);
                //运行成功
                if(ret != -1){
                    //添加功能
                    if(ty == CMD::orderType::SQL_CREATE){
                        if(objtype == "table"){
                            //注册新的表
                            printf("[create table] ok sign up for rights.\n");
                            sys_UserChecker.setNewTableWithRights(cur_user,objname);
                        }else if(objtype == "view"){
                            //注册新的视图
                            //验证视图的正确性
                            int view_ret = checkViewSQL(cur_user,objname);
                            if(view_ret >= 0){//视图验证正确 允许注册视图
                                printf("permit to sign up for view [%s]\n",objname.c_str());
                                sys_ViewKeeper.addView(objname,line);
                                sys_UserChecker.setNewTableWithRights(cur_user,objname);
                            }else{
                                printf("[error]-view sql error\n");
                            }
                        }
                        sys_UserChecker.show();
                    }else if(ty == CMD::orderType::SQL_DROP){
                        //如果删除的是基本表 需要连带删除其上的所有索引和视图
                        if(objtype == "table"){
                            //删除表的用户权限信息
                            sys_UserChecker.delOneTable(cur_user,objname);
                            //删除表上的所有索引
                            sys_IndexKeeper.deleteIndexOnTable(objname);
                            //删除表上的所有视图
                            //测试所有视图的有效性并删除无效的视图
                            delAllInVaildView();
                        }else if(objtype == "view"){
                            //删除视图
                            sys_ViewKeeper.delView(objname);
                            sys_UserChecker.delOneTable(cur_user,objname);
                            // sys_UserChecker.admit
                        }
                        sys_UserChecker.show();
                    }
                }else{
                    //运行失败
                    if(ty == CMD::orderType::SQL_CREATE){
                        if(objtype == "index"){
                            //create index运行失败 删除已经注册的index信息
                            sys_IndexKeeper.delIndex(objname);
                        }
                    }
                }
                printf("\n");
            }
        }
    }

    /* 程序收尾工作 */
    sys_UserChecker.WriteFile();
    sys_ViewKeeper.__writeData();
    DBIndex::IndexKeeperWriter(sys_IndexKeeper);

    //适配重新登录功能
    if(relogin){
        //重新登录
        goto relogin_flag;
    }
    
    printf("Over\n");
    return 0;
}





